using System;
using System.Reflection;
using System.Transactions;
using Oracle.ManagedDataAccess.Client;
using OracleInternal.Common;
using OracleInternal.ServiceObjects;

namespace OracleInternal.MTS
{
	internal abstract class FWPSPEManager : PSPEManager
	{
		private static MethodInfo s_promoteMethod;

		internal static void InitPromoteAndEnlistMethod(MethodInfo promoteMethod)
		{
			s_promoteMethod = promoteMethod;
		}

		internal FWPSPEManager(OracleConnectionImpl connImpl, Transaction txn, MTSTxnRM txnRM, MTSTxnBranch txnBranch)
			: base(connImpl, txn, txnRM, txnBranch)
		{
		}

		internal override byte[] InternalPromote(out Guid txnGuid)
		{
			s_promoteMethod.Invoke(m_sysTxn, new object[4]
			{
				m_mtsTxnRM.m_RMGuid,
				this,
				m_mtsTxnRM,
				EnlistmentOptions.None
			});
			m_mtsTxnRM.m_enlistedState = EnlistedState.Distributed;
			txnGuid = m_sysTxn.TransactionInformation.DistributedIdentifier;
			return null;
		}

		internal override bool InternalCommit()
		{
			return true;
		}

		internal override bool InternalRollback()
		{
			return true;
		}

		internal override void InternalHandlePromoteError()
		{
			if (m_bLocalTxnPromoted)
			{
				return;
			}
			try
			{
				try
				{
					if (m_connImpl.m_mtsTxnCtx != null && m_connImpl.m_mtsTxnCtx.m_txnType == MTSTxnType.Local)
					{
						OracleLogicalTransaction oracleLogicalTransaction = null;
						m_connImpl.m_mtsTxnCtx.m_localTxn.Rollback(null, ref oracleLogicalTransaction);
					}
				}
				catch
				{
				}
				finally
				{
					try
					{
						m_connImpl.SetAutoCommit(bAutoCommitOn: true);
					}
					catch
					{
					}
					try
					{
						if (m_connImpl.m_mtsTxnCtx != null)
						{
							m_connImpl.ResetMTSTxnCtx();
						}
					}
					catch
					{
					}
				}
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.FWPSPEManager, OracleTraceFuncName.InternalHandlePromoteError, "Rolled back local transactionLocal TxnID = " + m_sysTxn.TransactionInformation.LocalIdentifier + "using Conn ID = " + m_connImpl.m_endUserSessionId + " to DBInst = " + m_connImpl.m_instanceName);
				}
			}
			finally
			{
				try
				{
					if (ProviderConfig.m_bTraceLevelPrivate)
					{
						Trace.Write(OracleTraceLevel.Private, OracleTraceTag.MTS, OracleTraceClassName.FWPSPEManager, OracleTraceFuncName.InternalHandlePromoteError, "FWPSPEManager.HandlePromoteError(): Releasing Conn ID = " + m_connImpl.m_endUserSessionId + " to DBInst = " + m_connImpl.m_instanceName + "\tLocal TxnID " + m_sysTxn.TransactionInformation.LocalIdentifier);
					}
				}
				catch
				{
				}
				try
				{
					ResetForPromotedTxn(m_connImpl, m_sysTxn, m_sysTxn.TransactionInformation.LocalIdentifier);
				}
				catch
				{
				}
				try
				{
					m_mtsTxnRM.ReleaseRP(m_connStr, m_sysTxn);
				}
				catch
				{
				}
				m_connImpl = null;
			}
		}
	}
}
